#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<netinet/in.h>

#define MAXLINE 4096
#define MAX_EVENTS 128
#define SET_EPOLL

char buf[4096];

struct get_pkg{
		int len;
		char* content;
};

void str_handle(int fd, const char* buf, int n)
{
	int show_buf_size = n - 3;
	char* show_buf = (char*)malloc(show_buf_size);
	memset(show_buf, 0, show_buf_size);
	memcpy(show_buf, buf + 4, show_buf_size - 1);
	show_buf[show_buf_size] = '\0';
	printf("get msg from client: %s", show_buf);
	free(show_buf);
}

void events_handle(int connfd)
{
	int n;
	for(;;) {
		if((n = read(connfd, buf, MAXLINE)) == 0){
					printf("recv error\n");
					break;
				} else {
					str_handle(connfd, buf, n);
				}
	}
}

void conn_handle(int fd)
{	
	int connfd, epollfd, flag;
	struct get_pkg *pkg;

#ifdef SET_EPOLL
	if((epollfd = epoll_create(MAX_EVENTS)) == -1){
			printf("creat epoll failed\n");
			exit(0);
	}

	struct epoll_event events[MAX_EVENTS];
	struct epoll_event event;
	event.data.fd = fd;
	event.events = EPOLLIN;
	flag = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
	if(flag == -1){
			perror("epoll_ctl");
			exit(0);
	}
#endif
	int i, n;
	
	for(;;){
#ifdef SET_EPOLL
			n = epoll_wait(epollfd, events, MAX_EVENTS, -1);
			for(i = 0; i < n; i++){
					if((events[i].events & EPOLLERR) ||  
					   (events[i].events & EPOLLHUP) ||  
					   (!(events[i].events & EPOLLIN))) {
							fprintf(stderr, "epoll error\n");
							close(events[i].data.fd);
							continue;
					} else if (events[i].data.fd == fd) {
#endif
							if((connfd = accept(fd, NULL, NULL)) == -1) {
									printf("accept socket error\n");
									continue;
							}			
							events_handle(connfd);
#ifdef SET_EPOLL
					}
			}
#endif
	}
}


int main(int argc, char **argv)
{	
	int listenfd;
	pid_t childpid;
	struct sockaddr_in servaddr;

	if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
			printf("creat socket error\n");
			exit(0);
	}

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(6666);

	if(bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) == -1) {
			printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);
			exit(0);
	}

//允许环境变量LISTENQ覆盖调用者指定的值。
	int backlog = atoi("LISTENQ");
	char *ptr;
	if((ptr = getenv("LISTENQ")) != NULL)
			backlog = atoi(ptr);

	printf("--------------------initlization success------------------");
	if(listen(listenfd, 10) == -1){
			printf("listen socket error\n");
			exit(0);
	}
	
	conn_handle(listenfd);
	
	return 0;
}
